/* 
    函数兼容性之间比较复杂，需要考虑：
        1. 参数个数
        2. 参数类型
        3. 返回类型
    type 是类型别名
        type F1 = ()=>void ；//把函数F1() 定义为一种类型；
        let f1:F1; //f1 的类型是 F1()
*/

// 1. 参数个数：参数少的可以赋值给参数多的（参数多的兼容少的，和类兼容、接口兼容相反）
type F1 = (a: number) => void
type F2 = (a: number, b: number) => void
let f1: F1;
let f2: F2 = f1;//少的赋值给多的
let f11: F1 = f2;//error

// 2. 参数类型：相同位置的参数类型要相同或者兼容
// 2.1 相同位置的参数类型相同，都是原始类型
type F3 = (a: number) => void
let f3: F3;
f3 = f1; //f3 和 f1 相互兼容
f1 = f3;

// 2.2 相同位置的参数类型兼容，是对象类型
interface Point2D {
    x: number
    y: number
}

interface Point3D {
    x: number
    y: number
    z: number
}

type F4 = (p: Point2D) => void //相当于有2个参数
type F5 = (p: Point3D) => void //相当于有3个参数
let f4: F4
let f5: F5
// 此处不能用接口兼容性理解，要把对象拆开，把每个属性看成一个个参数，则 参数少的 f4 可以赋值给参数多的 f5
f5 = f4;//right
f4 = f5;//error

// 3. 返回值类型：只关注返回值本身即可
// 返回值是原始类型,相互兼容
type F6 = () => string
type F7 = () => string
let f6: F6;
let f7: F7;
f7 = f6;
f6 = f7;

// 返回值是对象类型，成员多的可以赋值给成员少的
type F8 = () => { name: string }
type F9 = () => { name: string, age: number }
let f8: F8;
let f9: F9;
f8 = f9;//right
f9 = f8;//error
